/* Bresenham octant code, which I should use eventually */
int x, y, d;
x = 0;
y = w;
d = 3-2*w;
while (x < y) {
gdImageSetPixel(im, cx+x, cy+y, color);
if (d < 0) {
d += 4 * x + 6;
} else {
d += 4 * (x - y) + 10;
y--;
}
x++;
}
if (x == y) {
gdImageSetPixel(im, cx+x, cy+y, color);
}
#endif
void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
{
int lastBorder;
/* Seek left */
int leftLimit, rightLimit;
int i;
leftLimit = (-1);
if (border < 0) {
/* Refuse to fill to a non-solid border */
return;
}
for (i = x; (i >= 0); i--) {
if (gdImageGetPixel(im, i, y) == border) {
break;
}
gdImageSetPixel(im, i, y, color);
leftLimit = i;
}
if (leftLimit == (-1)) {
return;
}
/* Seek right */
rightLimit = x;
for (i = (x+1); (i < im->sx); i++) {
if (gdImageGetPixel(im, i, y) == border) {
break;
}
gdImageSetPixel(im, i, y, color);
rightLimit = i;
}
/* Look at lines above and below and start paints */
/* Above */
if (y > 0) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
c = gdImageGetPixel(im, i, y-1);
if (lastBorder) {
if ((c != border) && (c != color)) {
gdImageFillToBorder(im, i, y-1,
border, color);
lastBorder = 0;
}
} else if ((c == border) || (c == color)) {
lastBorder = 1;
}
}
}
/* Below */
if (y < ((im->sy) - 1)) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
c = gdImageGetPixel(im, i, y+1);
if (lastBorder) {
if ((c != border) && (c != color)) {
gdImageFillToBorder(im, i, y+1,
border, color);
lastBorder = 0;
}
} else if ((c == border) || (c == color)) {
lastBorder = 1;
}
}
}
}
void gdImageFill(gdImagePtr im, int x, int y, int color)
{
int lastBorder;
int old;
int leftLimit, rightLimit;
int i;
old = gdImageGetPixel(im, x, y);
if (color == gdTiled) {
/* Tile fill -- got to watch out! */
int p, tileColor;
int srcx, srcy;
if (!im->tile) {
return;
}
/* Refuse to flood-fill with a transparent pattern --
I can't do it without allocating another image */
if (gdImageGetTransparent(im->tile) != (-1)) {
return;
}
srcx = x % gdImageSX(im->tile);
srcy = y % gdImageSY(im->tile);
p = gdImageGetPixel(im->tile, srcx, srcy);
tileColor = im->tileColorMap[p];
if (old == tileColor) {
/* Nothing to be done */
return;
}
} else {
if (old == color) {
/* Nothing to be done */
return;
}
}
/* Seek left */
leftLimit = (-1);
for (i = x; (i >= 0); i--) {
if (gdImageGetPixel(im, i, y) != old) {
break;
}
gdImageSetPixel(im, i, y, color);
leftLimit = i;
}
if (leftLimit == (-1)) {
return;
}
/* Seek right */
rightLimit = x;
for (i = (x+1); (i < im->sx); i++) {
if (gdImageGetPixel(im, i, y) != old) {
break;
}
gdImageSetPixel(im, i, y, color);
rightLimit = i;
}
/* Look at lines above and below and start paints */
/* Above */
if (y > 0) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
c = gdImageGetPixel(im, i, y-1);
if (lastBorder) {
if (c == old) {
gdImageFill(im, i, y-1, color);
lastBorder = 0;
}
} else if (c != old) {
lastBorder = 1;
}
}
}
/* Below */
if (y < ((im->sy) - 1)) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
c = gdImageGetPixel(im, i, y+1);
if (lastBorder) {
if (c == old) {
gdImageFill(im, i, y+1, color);
lastBorder = 0;
}
} else if (c != old) {
lastBorder = 1;
}
}
}
}
#ifdef TEST_CODE
void gdImageDump(gdImagePtr im)
{
int i, j;
for (i=0; (i < im->sy); i++) {
for (j=0; (j < im->sx); j++) {
printf("%d", im->pixels[j][i]);
}
printf("\n");
}
}
#endif
/* Code drawn from ppmtogif.c, from the pbmplus package
**
** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
** Lempel-Zim compression based on "compress".
**
** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
** The Graphics Interchange Format(c) is the Copyright property of
** CompuServe Incorporated. GIF(sm) is a Service Mark property of
** CompuServe Incorporated.
*/
/*
* a code_int must be able to hold 2**GIFBITS values of type int, and also -1
*/
typedef int code_int;
#ifdef SIGNED_COMPARE_SLOW
typedef unsigned long int count_int;
typedef unsigned short int count_short;
#else /*SIGNED_COMPARE_SLOW*/
typedef long int count_int;
#endif /*SIGNED_COMPARE_SLOW*/
static int colorstobpp(int colors);
static void BumpPixel (void);
static int GIFNextPixel (gdImagePtr im);
static void GIFEncode (FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
* Bump the 'curx' and 'cury' to point to the next pixel
*/
static void
BumpPixel(void)
{
/*
* Bump the current X position
*/
++curx;
/*
* If we are at the end of a scan line, set curx back to the beginning
* If we are interlaced, bump the cury to the appropriate spot,
* otherwise, just increment it.
*/
if( curx == Width ) {
curx = 0;
if( !Interlace )
++cury;
else {
switch( Pass ) {
case 0:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 4;
}
break;
case 1:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 2;
}
break;
case 2:
cury += 4;
if( cury >= Height ) {
++Pass;
cury = 1;
}
break;
case 3:
cury += 2;
break;
}
}
}
}
/*
* Return the next pixel from the image
*/
static int
GIFNextPixel(gdImagePtr im)
{
int r;
if( CountDown == 0 )
return EOF;
--CountDown;
r = gdImageGetPixel(im, curx, cury);
BumpPixel();
return r;
}
/* public */
static void
GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)